#include <iostream>
namespace lei {
template <typename T>

class unique_ptr {
 public:
  // 构造析构
  unique_ptr() noexcept = default;
  unique_ptr(T* ptr = nullptr) : ptr_(ptr) noexcept {
    std::cout << "unique_ptr construct, addr:" << this << std::endl;
  }
  unique_ptr(const unique_ptr&) = delete;
  unique_ptr& operator=(const unique_ptr&) = delete;
  unique_ptr(unique_ptr&& r) : ptr_(r.release()) noexcept {}
  unique_ptr& operator=(unique_ptr&& r) noexcept {
    reset(r.release());
    return *this;
  }

  ~unique_ptr() noexcept {
    std::cout << "unique_ptr deconstruct, addr:" << this << std::endl;
    // if (ptr_) delete ptr_;
    // delete nullptr;不会报错，不做任何操作
    delete ptr_;
  }
  // 运算符重载
  explicit operator bool() const noexcept { return ptr_; }
  T* operator->() const noexcept { return ptr_; }
  T& operator*() const { return *ptr_; }  // 可能抛出异常

  // 其他函数
  void swap(const unique_ptr& r) noexcept { std::swap(ptr_, r.ptr_); }
  T* get() const noexcept { return ptr_; }
  T* release() noexcept {
    T* tmp = ptr_;
    ptr_ = nullptr;
    return tmp;
  }
  void reset(T* ptr = nullptr) noexcept {
    if (ptr_) delete ptr_;
    ptr_ = ptr;
  }

 private:
  T* ptr_;
};
template <typename T, typename... Args>
auto make_unique(Args... args) {
  // return unique_ptr<T>(new T(std::forward<Args>(args)...));
  // vector{1,2}，与标准库不兼容
  return unique_ptr<T>(new T{std::forward<Args>(args)...});
}
}  // namespace lei
   // TODO:什么情况会抛出异常